
import Router from 'vue-router'
import XEUtils from 'xe-utils'
import TypeOfUtils from './data-type-utils'
import { constantRouters, constantRouterComponents, rootRouter } from '@/router/router-async'

// 应用配置
let appOptions = {
  router: undefined,
  store: undefined,
}

// 所有权限
const allAuthority = { permission: '*' }

// 登录白名单配置
const loginIgnore = {
  // 路由名称
  names: ['404', '403'],
  // 路由的地址
  paths: ['/login'],
  /**
   * 判断是否白名单
   * 
   * @param {Object} route  route对象
   * @return { boolean } 是否包含
   */
  includes (route) {
    return this.names.includes(route.name) || this.paths.includes(route.path)
  }
}

/**
 * 设置应用配置
 * @param options 应用参数
 */
 function setAppOptions(options) {
  const {router, store, i18n} = options
  appOptions.router = router
  appOptions.store = store
  appOptions.i18n = i18n
}

/**
 * 格式化路由
 * 
 * @param { Array } routes 路由数据配置
 * @author LiSong
 * @date 2022-5-12 16:21:52
 */
function formatRoutes (routes) {
  if (routes) {
    routes.forEach(route => {
      const { path } = route
      // 为了防止出现后端返回结果不规范，处理有可能出现拼接出两个反斜杠
      if (!path.startsWith('http')) {
        route.path = path.replace('//', '/')
      }
      // 为了防止出现路由只有名称没有反斜线的情况，自行拼接上反斜线
      if (!path.startsWith('/') && path !== '*') {
        route.path = '/' + path
      }
    })
    // this.formatAuthority(routes)
  }
}

/**
 * 格式化路由的权限配置
 * 
 * @param {Array} routes 路由数据
 * @param {Array} pAuthorities 父级路由权限配置
 * @author LiSong
 * @date 2022-5-12 16:27:14
 */
function formatAuthority (routes, pAuthorities = []) {
  if (routes) {
    const defaultAuthority = pAuthorities[pAuthorities.length - 1] || allAuthority
    routes.forEach(route => {
      const meta = route.meta
      if (meta) {
        let authority = {}
        if (!meta.authority) {
          authority = defaultAuthority
        } else if (TypeOfUtils.isString(meta.authority)) {
          authority.permission = meta.authority
        } else if (TypeOfUtils.isObject(meta.authority)) {
          authority = meta.authority
          const { role } = authority
          if (TypeOfUtils.isString(role)) {
            authority.role = [role]
          }
          if (!authority.permission && !authority.role) {
            authority = defaultAuthority
          }
        }
        meta.authority = authority
      } else {
        const authority = defaultAuthority
        route.meta = { authority }
      }
      route.meta.pAuthorities = pAuthorities
      if (route.children) {
        formatAuthority(route.children, [...pAuthorities, route.meta.authority])
      }
    })
  }
}


/**
 * 加载配置（动态路由）
 * 
 * @param { Array } routesConfig 路由配置信息
 * @author LiSong
 * @date 2022-05-15 17:50:11
 */
function loadRoutes(routesConfig) {
  //兼容 0.6.1 以下版本
  /*************** 兼容 version < v0.6.1 *****************/
  if (arguments.length > 0) {
    const arg0 = arguments[0]
    if (arg0.router || arg0.i18n || arg0.store) {
      routesConfig = arguments[1]
      console.error('the usage of signature loadRoutes({router, store, i18n}, routesConfig) is out of date, please use the new signature: loadRoutes(routesConfig).')
      console.error('方法签名 loadRoutes({router, store, i18n}, routesConfig) 的用法已过时, 请使用新的方法签名 loadRoutes(routesConfig)。')
    }
  }
  /*************** 兼容 version < v0.6.1 *****************/

  // 应用配置
  const { router, store } = appOptions
  // 传入配置参数不为空
  if (routesConfig) {
    store.commit('account/setRoutesConfig', routesConfig)
  } else {
  // 传入配置参数为空，取本地缓存数据
    routesConfig = store.getters['account/routesConfig']
  }

  // 是否开启了异步路由模式
  const asyncRoutes = store.state.settings.asyncRoutes
  if (asyncRoutes) {
    if (routesConfig && routesConfig.length > 0) {
      // 进行路由转换
      const asyncRoutes = parseRoutes(routesConfig)
      let routes = XEUtils.clone(rootRouter, true)
      routes.children = asyncRoutes
      let finalRoutes = mergeRoutes(constantRouters, [ routes ])
      console.log('finalRoutes', finalRoutes)
      router.options = { ...router.options, routes: finalRoutes }
      router.matcher = new Router({ ...router.options, routes:[] }).matcher
      // 配置动态路由数据
      // finalRoutes.forEach(item => { router.addRoute(item) })
      router.addRoutes(finalRoutes)
    }
  }

  // 初始化Admin后台菜单数据
  const rootRouters = router.options.routes.find(item => item.path === '/')
  const menuRoutes = rootRouters && rootRouters.children
  if (menuRoutes) {
    console.log('menuRoutes', menuRoutes)
    store.commit('settings/setMenuData', menuRoutes)
  }

}

/**
 * 根据路由配置解析路由
 * 
 * @param {Array} routesConfig 路由配置
 */
function parseRoutes (routesConfig, parentRoute) {
  return routesConfig.map(item => {
    const meta = {
      role: item?.meta?.role,
      page: item?.meta?.page,
      query: item?.query,
      params: item?.params,
      title: item?.meta?.title,
      target: item?.meta?.target,
      invisible: false,
      keepAlive: false,
      authority: '*',
      permission: item?.meta?.permission,
    }
    const currentRouter = {
       // 如果路由设置了 path，则作为默认 path，否则 路由地址 动态拼接生成如 /dashboard/workplace
       path: item.path || `${(parentRoute && parentRoute.path) || ''}/${item.key}`,
       // 路由名称，建议唯一
       name: item.name || item.key || '',
       // 是否隐藏
       hidden: item.hidden,
       // 该路由对应页面的 组件 :方案2 (动态加载) 
       component: transformComponent(item.component),
       // 图标
       icon: item.icon || '',
       // meta 页面标题，角色，图标，权限......
       meta: meta
    }
    if (currentRouter.hidden) {
      currentRouter.meta.invisible = true
    }
    // 为了防止出现后端返回结果不规范，处理有可能出现拼接出两个 反斜杠
    if (!currentRouter.path.startsWith('http')) {
      currentRouter.path = currentRouter.path.replace('//', '/')
    }
    // 格式化路由路径数据
    if (!currentRouter.path.startsWith('/') && currentRouter.path !== '*') {
      currentRouter.path = '/' + path
    }
    // 设置重定向
    item.redirect && (currentRouter.redirect = item.redirect)
    // 是否有子菜单，并递归处理
    if (item.children && item.children.length > 0) {
      // 递归调用
      currentRouter.children = parseRoutes(item.children, currentRouter)
    }
    return currentRouter
  })
}

/**
 * 合并路由
 * 
 * @param {Array} routes 路由配置
 */
function mergeRoutes (target, routes) {
  const routesMap = {}
  target.forEach(item => routesMap[item.path] = item)
  routes.forEach(item => routesMap[item.path] = item)
  return Object.values(routesMap)
}

/**
 * 转换组件地址
 * 
 * @param {String} path 组件地址
 * @author LiSong
 * @date 2022-5-16 09:57:31
 */
function transformComponent (path) {
  if (constantRouterComponents[path]) {
    return constantRouterComponents[path]
  } else {
    //  || (() => import(`@/views/${item.component}`))
    return function (resolve) {
      import(`@/views${path}`).then(mod => {
        resolve(mod)
      })
    }
  }
}

/**
 * 从路由 path 解析 i18n key
 * @param path
 * @returns {*}
 */
 function getI18nKey(path) {
  const keys = path.split('/').filter(item => !item.startsWith(':') && item != '')
  keys.push('name')
  return keys.join('.')
}

/**
 * 加载导航守卫
 * 
 * @param {Object} guards 
 * @param {Object} options
 * @author LiSong
 * @date 2022-5-16 11:35:39
 */
function loadGuards (guards, options) {
  const { beforeEach, afterEach } = guards
  const { router } = options
  beforeEach.forEach(guard => {
    if (guard && TypeOfUtils.isFunction(guard)) {
      router.beforeEach((to, from, next) => guard(to, from, next, options))
    }
  })
  afterEach.forEach(guard => {
    if (guard && TypeOfUtils.isFunction(guard)) {
      router.afterEach((to, from) => guard(to, from, options))
    }
  })
}

export {
  loginIgnore, loadRoutes, loadGuards, getI18nKey,
  setAppOptions, formatRoutes, formatAuthority
}